using System;
using System.Reflection;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Threading;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text.RegularExpressions;
using ACM.cmsarea08;
using ACM.cmsarea08.mainconfiguration;



namespace ACM.cmsarea08.Core {
	public class ImageResizer :  IHttpAsyncHandler { //IHttpHandler

       public bool IsReusable { get { return true; } }
      public void ProcessRequest(System.Web.HttpContext contesto)
        {
      	//non usato.
         }
	  public IAsyncResult BeginProcessRequest(HttpContext ctx, AsyncCallback cb, object obj)
	  {
	    AsyncImageResizerState reqState = new AsyncImageResizerState(ctx, cb, obj);
	    AsyncImageResizerRequest ar = new AsyncImageResizerRequest(reqState);
	    ThreadStart ts = new ThreadStart(ar.ProcessRequest);
	    Thread t = new Thread(ts);
	    t.Start();
	    return reqState;
	  }
        
	  public void EndProcessRequest(IAsyncResult ar)
	  {
	    AsyncImageResizerState ars = ar as AsyncImageResizerState;
	    if (ars != null)
	    {
	     // Clean Up
	    }
	  }      
      
        
	}
	
	public class AsyncImageResizerState : IAsyncResult {
		
		internal HttpContext _ctx;
		internal AsyncCallback _cb;
		internal object _dati;
		private bool _iscompleted = false;
		private ManualResetEvent _callCompleteEvent = null;
		
		public AsyncImageResizerState(HttpContext ctx, AsyncCallback cb, object dati) {
			_ctx = ctx;
			_cb = cb;
			_dati = dati;
			
		}
		internal void CompleteRequest() {
			_iscompleted = true;
			if(this==null) return;
			lock(this) {
				if(_callCompleteEvent!=null) {
					_callCompleteEvent.Set();
				}
				 if (_cb != null)
				 	_cb(this);
			}
		}
		public object AsyncState {
			get { return _dati; }
		}
		public bool CompletedSynchronously {
			get { return false; }
		}
		public bool IsCompleted            {
			get { return _iscompleted; }
		}
		public WaitHandle AsyncWaitHandle {
			get {
				lock(this) {
					if(_callCompleteEvent == null) 
						_callCompleteEvent = new ManualResetEvent(false);
					return _callCompleteEvent;
				}
			}
		}



	}
	class AsyncImageResizerRequest
	{

	  private AsyncImageResizerState _asyncRequestState;
	
	  public AsyncImageResizerRequest(AsyncImageResizerState ars)
	  {
	    _asyncRequestState = ars;
	  }
	    
	  public void ProcessRequest()
	  {
            string fileName = "";
            string fileSource = "";
            string fileKey = "";
            
            int w = 0;
            int h = 0;
            //string FileStreamData = "";
            //FileStreamData = HttpUtility.UrlDecode(HttpContext.Current.Request.Params["dt"].ToString());
            if(_asyncRequestState._ctx.Request.Params["so"]!=null) {
            	fileSource = _asyncRequestState._ctx.Request.Params["so"].ToString();
            }
            if(_asyncRequestState._ctx.Request.Params["sn"]!=null) {
            	fileName = _asyncRequestState._ctx.Request.Params["sn"].ToString();
            }
            
            
            /* leggo i size dell'image */
            if(_asyncRequestState._ctx.Request.Params["sw"]!=null) {
            	Int32.TryParse(_asyncRequestState._ctx.Request.Params["sw"].ToString(),out w);
            }
            if(_asyncRequestState._ctx.Request.Params["sh"]!=null) {
            	Int32.TryParse(_asyncRequestState._ctx.Request.Params["sh"].ToString(),out h);
            }
            /* leggo i size dell'image */
            fileKey = ACM.cmsarea08.Function.TextClass.textclass.ToFileName(fileSource) + 
            	w.ToString() + "-"+h.ToString();
			Function.CacheFileObjectInfo imageInfo = 
				Function.CacheManager.cachemanager.getCacheFileObjectInfo(_asyncRequestState._ctx,fileKey);
            if(imageInfo.exists==true || imageInfo.filename.Trim().Length>0) {
            	Function.CacheManager.cachemanager.TransmitCacheFileObject(fileKey,_asyncRequestState._ctx,false);
            	_asyncRequestState.CompleteRequest(); return;            	
			}
            
            
            if (fileName.Trim() == "") { Nulla(); _asyncRequestState.CompleteRequest();return; }
            if (fileSource.Trim() == "") { Nulla(); _asyncRequestState.CompleteRequest();return; }
             LoadIMAGE(fileName,fileSource,w,h,fileKey);
	  	
	  	
		//finito.
	    _asyncRequestState.CompleteRequest();
	  }
	  
	  
		private void Nulla() { 
            _asyncRequestState._ctx.ApplicationInstance.Response.StatusCode = 404;
            _asyncRequestState._ctx.ApplicationInstance.CompleteRequest();
		}			
		private void Nulla(string errore) { 
        	//_asyncRequestState._ctx.Response.Clear();
        	_asyncRequestState._ctx.Response.ContentType = "text/html";
        	_asyncRequestState._ctx.Response.Write(errore);
            _asyncRequestState._ctx.Response.End();
            _asyncRequestState.CompleteRequest();
		}	
        private void LoadIMAGE(string filename,string fileSource, int w, int h,string fileKey)
        {
            try
            {
            	string percorso = _asyncRequestState._ctx.Server.MapPath(fileSource);
            	if(!System.IO.File.Exists(percorso)) {
            		Nulla("NO FILE");
            		_asyncRequestState.CompleteRequest();
            		return;
            	}
            	
                System.Drawing.Image im = System.Drawing.Image.FromFile(percorso);
                if (im == null) { Nulla("NIENTE"); _asyncRequestState.CompleteRequest();return; }
                if(w==0)
                	w = im.Width;
                if(h==0)
                	h = im.Height;
                
                decimal wnew = 0;
                decimal hnew = 0;
                decimal cwnew = 0;
                decimal chnew = 0;                
                decimal scale = 0;
                int scaleby = -1;
                if(w<0) 
                	scaleby = 1;
                else if (h<0)
                	scaleby = 2;
                else
                	scaleby=0;
                
                if(scaleby>0) {
                	scale = ((decimal)im.Width / (decimal)im.Height);
                	if(scaleby == 1) {
                		chnew = hnew = h;
                		cwnew = wnew = (decimal) h*scale;
                	}
                	if(scaleby == 2) {
                		chnew = hnew = (decimal) w/scale;
                		cwnew = wnew = w;
                	}                	
                } else {
                	cwnew = wnew = w;
                	chnew = hnew = h;
                }
                
                //se le dime sono maggiori di cwnew e chnew:
                
                if(im.Height> chnew || im.Width>cwnew) {
                	//scala comunque:
//                	scale = 
//                		(im.Width>=im.Height ? (
//                			((decimal)im.Width/(decimal)im.Height) ) :
//                		 ( ((decimal)im.Height/(decimal)im.Width)  ) );
			scale = ((decimal)im.Width/(decimal)im.Height) ;

                	if(im.Height>im.Width) {
						wnew =   (scale<1?((decimal)h*scale):((decimal)h/scale));
						hnew =   h;
                	} else {
						wnew =   w;
						hnew =   (scale<1?((decimal)w*scale):((decimal)w/scale));
                	}
                } else {
                	hnew = im.Height;
                	wnew = im.Width;
                }
                
                
                System.Drawing.Image oImage = new Bitmap((int)wnew,(int)hnew,im.PixelFormat);
                Graphics ograp = Graphics.FromImage(oImage);
                ograp.Clear(Color.White);
                ograp.CompositingQuality = CompositingQuality.HighQuality;
                ograp.SmoothingMode = SmoothingMode.HighQuality;
                ograp.InterpolationMode = InterpolationMode.HighQualityBicubic;
                
//                int posX = 0;
//                int posY = 0;
//                posX = (int)(cwnew/(decimal)2 - wnew/(decimal)2);
//                posY = (int)(chnew/(decimal)2 - hnew/(decimal)2);
                Rectangle orec = new Rectangle(0,0,(int)wnew,(int)hnew);
                ograp.DrawImage(im,orec);
                //System.Drawing.Image low = im.GetThumbnailImage((int)wnew, (int)hnew, null, IntPtr.Zero);
                //_asyncRequestState._ctx.Response.ContentType = "image/jpeg";
                string extension = "";
                extension = filename.Substring(filename.LastIndexOf('.')).ToLower();
                switch (extension)
                {
                    case ".gif":
                        _asyncRequestState._ctx.Response.ContentType = "image/gif";
                        break;
                    case ".jpg":
                        _asyncRequestState._ctx.Response.ContentType = "image/jpeg";
                        break;
                    case ".jpeg":
                        _asyncRequestState._ctx.Response.ContentType = "image/jpeg";
                        break;
                    case ".png":
                        _asyncRequestState._ctx.Response.ContentType = "image/png";
                        break;
                    default:
                        throw new NotSupportedException("Unrecognized image type." + extension);
                } 
                
                oImage.Save(_asyncRequestState._ctx.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                try {
                //	Function.CacheManager.cachemanager.RemoveCacheFileObject(_asyncRequestState._ctx,chiave);
                System.IO.MemoryStream str = new System.IO.MemoryStream();
                oImage.Save(str,System.Drawing.Imaging.ImageFormat.Jpeg);
                Function.CacheManager.cachemanager.setCacheFileObject(
                	_asyncRequestState._ctx,fileKey,filename +"#" +Convert.ToBase64String(str.ToArray()),360,true);
                str.Close();
                str.Dispose();
                } catch (Exception ex) {
                	ACM.cmsarea08.mainconfiguration.MainLogger.logger.SetLogUnique("NON SALVATO EDITED: " + fileKey,fileKey,fileKey);
                }                
                _asyncRequestState._ctx.Response.End();
                //low.Dispose();
                oImage.Dispose();
                im.Dispose();
                
            }
            catch (Exception ex)
            {
                //non renderizzo nulla.
                Nulla(ex.ToString());
                _asyncRequestState.CompleteRequest();
            }
        }
	  
	}
	
	
	
	
}
